#function(data_tb)


#import toolbox;
#import props;
#import ui;

// 链路仿真工具

local tb = toolbox.new_toolbox();
tb.title = _kT("LinkSimulation#Toolbox");

// 预定义的方法
local makeDirfuncFromData;  // 从数据得到方向图函数
local GetTxFunc;            // 获取发射机的方向图函数
local GetRxFunc;            // 获取接收机的方向图函数
local GetPropFunc;          // 获取传播模型函数

// 工具箱初始化
tb.evt_init = function(model)
{
    local ec = model.evtmgr;

    // 全局设置
    ec.wm_var("unit.power", "unit.power", 1);           // 功率单位，可选W和mW两种
    ec.wm_var("unit.frequency", "unit.frequency", 3);   // 0: Hz；1：kHz；2：MHz；3：GHz；4：THz
    ec.wm_var("unit.length", "unit.length", 1);         // 0：m；1：km
    ec.wm_var("freq.val", "freq.val", "1.0");

    
    // 发射机参数
    ec.wm_var("Tx.type", "Tx.type", 0);           // 0：全向天线；1：导入文件（相比全向天线）
    ec.wm_var("Tx.file", "Tx.file", "");          // 发射源性能文件（方向图）
    ec.wm_var("Tx.power", "Tx.power", "1");       // 发射机功率

    // 接收机参数
    // 接收机灵敏度 S = dB(kTB) + NF + SNR
    ec.wm_var("Rx.file", "Rx.file",  "");          // 接收机性能文件（最大方向图）
    ec.wm_var("Rx.temp", "Rx.temp",  "300");       // 接收机工作温度
    ec.wm_var("Rx.band", "Rx.band",  "1000");      // 接收机工作带宽
    ec.wm_var("Rx.nf",   "Rx.nf",    "80");        // 噪声系数
    ec.wm_var("Rx.SNR",  "Rx.SNR" , "-40");       // 信噪比

    // 传播参数
    ec.wm_var("propagation.model", "propagation.model", 0);                     // 传播模型：0 - 自由空间传播
    ec.wm_var("propagation.distance_min", "propagation.distance_min", "1");     // 传播距离最小值
    ec.wm_var("propagation.distance_max", "propagation.distance_max", "100");   // 传播距离最大值
    ec.wm_var("propagation.distance_num", "propagation.distance_num", "101");   // 分析距离的间隔

    // 发射机类型
    ec.gp_beg("TxType_optdata", "OptionData");
        ec.gp_add(_hT("FromFile"), 0);
        ec.gp_add(_hT("OmnidirectionalAntenna"), 1);  // 全向天线（0 dBi）
    ec.gp_end();

    // 传播模型
    ec.gp_beg("Propagation_optdata", "OptionData");
        ec.gp_add(_hT("FreeSpacePropagationModel"), 0);
    ec.gp_end();


    // 单位选项
    ec.gp_beg("UnitPower_optdata", "OptionData");
        ec.gp_add(_hT("W"), 0);
        ec.gp_add(_hT("mW"), 1);
    ec.gp_end();
    ec.gp_beg("UnitLength_optdata", "OptionData");
        ec.gp_add(_hT("m"), 0);
        ec.gp_add(_hT("km"), 1);
    ec.gp_end();
    ec.gp_beg("UnitFrequency_optdata", "OptionData");
        ec.gp_add(_hT("Hz"), 0);
        ec.gp_add(_hT("KHz"), 1);
        ec.gp_add(_hT("MHz"), 2);
        ec.gp_add(_hT("GHz"), 3);
        ec.gp_add(_hT("THz"), 4);
    ec.gp_end();



    local viewdata = ec.wm_cmd("ViewData");
    viewdata.do_cmd_execute = function(param, model, evtmgr)
    {
        model.transfer_data(-1);

        // 绘制增益图
        try
        {
            local idata = table();
            idata.TxFunc, idata.TxData = GetTxFunc(model.data);
            idata.RxFunc, idata.RxData = GetRxFunc(model.data);
            // idata.PropFunc = GetPropFunc(model.data);

            local tb = exec("app:/scripting/data/toolbox/toolbox.simlink/viewdata.mx", idata);
            local tb1 = toolbox.create(tb);
            ui.window.create(tb1).show();
        }catch(e)
        {
            logger.log_error(e);
        }
    };

    local launch = ec.wm_cmd("Launch");
    launch.do_cmd_execute = function(param, model, evtmgr)
    {
        model.transfer_data(-1);

        local up = [1, 1e-3] [model.data["unit.power"]];
        local ul = [1, 1e3]  [model.data["unit.length"]];
        local uf = [1, 1e3, 1e6, 1e9, 1e12] [model.data["unit.frequency"]];

        try
        {
            local idata = table();
            // 获得发射机参数
            local TxFunc = GetTxFunc(model.data);

            // 计算接收机参数
            local RxFunc = GetRxFunc(model.data);

            // 传播函数
            // 输入距离返回一个dB数值
            local PropFunc = GetPropFunc(model.data);


            // 准备智能数据
            idata.ul = ul;
            idata.uf = uf;
            idata.up = up;

            local fstr = model.data["freq.val"];
            idata.freq = eval1(model.data["freq.val"]);

            idata.TxFunc = TxFunc;
            idata.RxFunc = RxFunc;


            // 功率
            idata.TxPower = eval1(model.data["Tx.power"]);

            // kTB -> 计算
            idata.RxTemp = eval1(model.data["Rx.temp"]);
            idata.RxBand = eval1(model.data["Rx.band"]);
            idata.RxNF   = eval1(model.data["Rx.nf"]);
            idata.RxSNR  = eval1(model.data["Rx.SNR"]);

            // 其他参数
            idata.PropFunc = PropFunc;
            idata.distance_min = eval1(model.data["propagation.distance_min"]);
            idata.distance_max = eval1(model.data["propagation.distance_max"]);
            idata.distance_num = eval1(model.data["propagation.distance_num"]);

            // 启动智能数据
            local tb = exec("app:/scripting/data/toolbox/toolbox.simlink/simlink.mx", idata);
            local tb1 = toolbox.create(tb);
            ui.window.create(tb1).show();
        }catch(e)
        {
            logger.LogError(e);
        }
    };
};


tb.dlg_init = function(ctx)
{


    local km = props.bind(ctx);

    km.win("toolbox.dialog",  km.label(_hT("toolbox.simlink")).flags(km.IWND_NO_RESIZABLE).sprops("icon", "simlink"));
    km.win("row", km.ld(5));
        km.win("col", km.ld(3).label(_hT("GlobalSettings")));
            // km.win("row", km.proportion(2).label(_hT("GlobalSettings")));
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("unit.power")));
                    km.add("combo", km.ld(2).name("unit.power").flags(km.IWND_READONLY | km.IWND_EXPAND).optdata("UnitPower_optdata"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("unit.frequency")));
                    km.add("combo", km.ld(2).name("unit.frequency").flags(km.IWND_READONLY | km.IWND_EXPAND).optdata("UnitFrequency_optdata"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("unit.length")));
                    km.add("combo", km.ld(2).name("unit.length").flags(km.IWND_READONLY | km.IWND_EXPAND).optdata("UnitLength_optdata"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Frequency")));
                    km.add("expression", km.ld(2).name("freq.val"));
                km.end();
            // km.end();
        km.end();
        km.win("col", km.ld(3));
            // 发射机参数
            km.win("row", km.proportion(2).label(_hT("TxSettings")));
                // 发射机类型
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Tx.type")));
                    km.add("combo", km.ld(2).name("Tx.type").flags(km.IWND_READONLY | km.IWND_EXPAND).optdata("TxType_optdata"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("File")));
                    km.add("filectrl", km.ld(2).name("Tx.file"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Power")));
                    km.add("expression", km.ld(2).name("Tx.power"));
                km.end();
            km.end();

            km.win("row", km.proportion(2).label(_hT("RxSettings")));
                // 接收机参数
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("File")));
                    km.add("filectrl", km.ld(2).name("Rx.file"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Temperature").."(K)"));
                    km.add("expression", km.ld(2).name("Rx.temp"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Bandwidth").."(Hz)"));
                    km.add("expression", km.ld(2).name("Rx.band"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("RxNF").."(dB)"));
                    km.add("expression", km.ld(2).name("Rx.nf"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("SNR").."(dB)"));
                    km.add("expression", km.ld(2).name("Rx.SNR"));
                km.end();
            km.end();

            km.win("row", km.proportion(2).label(_hT("PropagationSettings")));
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("PropagationModel")));
                    km.add("combo", km.ld(2).name("propagation.model").flags(km.IWND_READONLY | km.IWND_EXPAND).optdata("Propagation_optdata"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Distance.Min")));
                    km.add("expression", km.ld(2).name("propagation.distance_min"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Distance.Max")));
                    km.add("expression", km.ld(2).name("propagation.distance_max"));
                km.end();
                km.win("col", km.ld(3));
                    km.add("label", km.ld(1).label(_hT("Distance.Num")));
                    km.add("expression", km.ld(2).name("propagation.distance_num"));
                km.end();
            km.end();
        km.end();
        km.win("col", km.ld(3));
            km.add("space", km.ld(5));
            km.add("button", km.ld(1).name("ViewData").label(_hT("ViewData")));
            km.add("button", km.ld(1).name("Launch").label(_hT("Launch"))); // 弹出对应信号处理智能数据
            km.add("button",km.name(_hT("Help")).size(100,27).sprops("helpuri","#help_toolbox_LinkSimulation"));
        km.end();
    km.end();
    km.end();
};


makeDirfuncFromData = function(phi, gain_dB)
{
    local gain = 10 .^ (gain_dB/10);
    if(math.mod(phi[0] - phi[end], 360) != 0)
    {
        // 缺少最后一个角度，则处理成重复整数周期
        local dphi = math.mod(phi[0] - phi[end], 360);
        phi[end+1] = phi[end] + dphi;
        gain[end+1] = gain[0];
    }
    // println('gain: ' .. gain);
    // println('phi: ' .. phi);
    // 周期边界修正
    local df = (gain[1] - gain[end-1]) / math.mod(phi[1] - phi[end-1], 360);
    local f0 = math.pchip(phi, gain, "auto", [df, df]);

    local pref = phi[0];
    local f = function[=](p)
    {
        return f0(math.mod(p - pref, 360) + pref);
    };

    return f;
};

GetTxFunc = function (data)
{
    local type = data["Tx.type"];
    local TxFunc;
    switch(data["Tx.type"])
    {
    case 0:
    {
        // 导入数据作为方向图
        // 数据要求2列，角度-增益
        // 角度制
        local txdata = io.load_txt(data["Tx.file"]);
        if(txdata.size(1) < 2 || txdata.size(0) < 2)
        {
            throw("invalid_data_size");
        }

        local phi     = txdata[:, 0];
        local gain_dB = txdata[:, 1];
        TxFunc = makeDirfuncFromData(phi, gain_dB);
        
        return TxFunc, txdata;
    }
    case 1:
        // 全向天线标准幅度为1
        TxFunc = function(p)
        {
            if(is_array(p))
            {
                return ones(p.size());
            }else
            {
                return 1.0;
            }
        };
    }

    return TxFunc;
};

GetRxFunc = function (data)
{
    local rxdata = io.load_txt(data["Rx.file"]);
    if(rxdata.size(1) < 2 || rxdata.size(0) < 2)
    {
        throw("invalid_data_size");
    }

    local phi = rxdata[:, 0];
    local gain_dB = rxdata[:, 1];

    return makeDirfuncFromData(phi, gain_dB), rxdata;
};

GetPropFunc = function (data)
{
    switch(data["propagation.model"])
    {
    case 0:
        // Friis 公式
        return @(D_over_lambda)
        {
            return 1.0 ./ (4 * pi * D_over_lambda).^2;
        };
    }
};

return toolbox.create(tb);